package com.tarena.lbs.marketing.web.service;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.dao.PO;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.api.BasicApi;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.marketing.web.dao.repository.CouponCodeRepository;
import com.tarena.lbs.marketing.web.dao.repository.CouponRepository;
import com.tarena.lbs.marketing.web.thread.AuthenticationUtil;
import com.tarena.lbs.pojo.basic.dto.AdminDTO;
import com.tarena.lbs.pojo.marketing.param.CouponParam;
import com.tarena.lbs.pojo.marketing.po.CouponCodePO;
import com.tarena.lbs.pojo.marketing.po.CouponPO;
import com.tarena.lbs.pojo.marketing.vo.CouponVO;
import com.tarena.lbs.pojo.stock.param.CouponStockParam;
import com.tarena.lbs.stock.api.StockApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CouponService {
    @Autowired
    private CouponRepository couponRepository;
    @Autowired
    private CouponCodeRepository couponCodeRepository;
    public PageResult<CouponVO> couponPage() throws BusinessException {
        //1.获取登录用户的id adminId 检查角色是否是SHOP
        Integer adminId=getUserId(Roles.SHOP);
        //2.远程调用 获取 basic服务返回的admin详情 拿到businessId;
        Integer businessId=getBusinessId(adminId);
        //3.查询列表 当前商家所有优惠券 封装 分页返回值
        List<CouponPO> pos= getCouponsByBusinessId(businessId);
        PageResult<CouponVO> voPage=new PageResult<>(1,10);
        voPage.setTotal(100L);
        List<CouponVO> vos=null;
        if (CollectionUtils.isNotEmpty(pos)){
            vos=pos.stream().map(po->{
                CouponVO vo=new CouponVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    private List<CouponPO> getCouponsByBusinessId(Integer businessId) {
        //select * from coupon where business_id=#{}
        QueryWrapper<CouponPO> query=new QueryWrapper<>();
        query.eq("business_id",businessId);
        return couponRepository.list(query);
    }

    @DubboReference
    private BasicApi basicApi;
    private Integer getBusinessId(Integer adminId) throws BusinessException {
        //使用 basic服务提供的接口 查询admin
        AdminDTO adminDto = basicApi.getAdminDetail(adminId);
        //断言空
        Asserts.isTrue(adminDto==null,new BusinessException("-2","商家账号不存在"));
        //返回admin详情中的 businessId
        return adminDto.getBusinessId();
    }

    private Integer getUserId(Roles role) throws BusinessException {
        //拿到认证对象
        UserPrinciple userPrinciple = AuthenticationUtil.get();
        //断言空
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","认证解析失败"));
        //断言角色是否等于入参role
        Asserts.isTrue(userPrinciple.getRole()!=role,new BusinessException("-2","权限不足"));
        //返回id
        return userPrinciple.getId();
    }
    @Transactional(rollbackFor = Exception.class)
    public void couponAdd(CouponParam couponParam) throws BusinessException {
        //1.拿到userId
        Integer userId = getUserId(Roles.SHOP);
        //2.利用userId查询admin详情 获取businessId
        Integer businessId = getBusinessId(userId);
        //3.封装数据CouponPO 写入到数据库 coupon
        CouponPO couponPO=assembleCouponPO(couponParam,businessId);
        couponRepository.save(couponPO);//新增写入之后 回填的id属性
        //4.封装CouponCodePO list 批量写入到数据库 coupon_code
        //List<CouponCodePO> couponCodePos=assembleCouponCodePos(couponPO);
        //couponCodeRepository.saveBatch(couponCodePos,1000);
        //5.stock远程调用初始化库存
        initCouponStock(couponPO);
    }
    @DubboReference
    private StockApi stockApi;
    private void initCouponStock(CouponPO couponPO) throws BusinessException {
        //1.准备一个入参
        CouponStockParam param=new CouponStockParam();
        param.setCouponId(couponPO.getId());
        param.setBusinessId(couponPO.getBusinessId());
        param.setNum(couponPO.getMaxUsageLimit());
        //2.调用
        Boolean result = stockApi.initCouponStock(param);
        //3.根据返回值 判断如何处理结果(分布式事务--一致性选型)
        Asserts.isTrue(!result,new BusinessException("-2","库存初始化失败,回滚"));
    }

    private List<CouponCodePO> assembleCouponCodePos(CouponPO couponPO) {
        //1.获取当前优惠券 发行总量 maxUsageLimit
        Integer maxUsageLimit = couponPO.getMaxUsageLimit();
        //2.准备一个集合返回对象 循环遍历总量数字的次数 每次封装一个po对象 关联这个优惠券 生成唯一code编码
        List<CouponCodePO> pos=new ArrayList<>();
        for (int i=0;i<maxUsageLimit;i++){
            CouponCodePO po=new CouponCodePO();
            po.setBusinessId(couponPO.getBusinessId());
            po.setCouponId(couponPO.getId());
            po.setStatus(0);//0 表示 待使用 1 已使用 2 已过期
            po.setCreateAt(couponPO.getCreateAt());
            po.setUpdateAt(couponPO.getUpdateAt());
            //每一个优惠券券码 都是唯一字符串
            String code= UUID.randomUUID().toString().replace("-","");
            po.setCouponCode(code);
            pos.add(po);
        }
        return pos;
    }

    private CouponPO assembleCouponPO(CouponParam couponParam, Integer businessId) {
        //1.表单数据 能拷贝
        CouponPO po=new CouponPO();
        BeanUtils.copyProperties(couponParam,po);
        //2.业务层填补 属性
        //2.1 所属商家
        po.setBusinessId(businessId);
        //2.2 优惠券状态  0 待激活  1待使用 2过期 3作废
        po.setStatus(1);
        //2.3 管理状态 启用0  禁用1
        po.setEnableStatus(0);
        //2.4 通用字段 创建更新时间 now
        Date now=new Date();
        po.setCreateAt(now);
        po.setUpdateAt(now);
        try{
            //2.5 前端传递优惠券 有效时间 字符串 ,数据写入 时间是date 手动转化 2021-11-19
            po.setStartDate(DateUtils.parseDate(couponParam.getStartDate(),"yyyy-MM-dd HH:mm:ss"));
            po.setEndDate(DateUtils.parseDate(couponParam.getEndDate(),"yyyy-MM-dd HH:mm:ss"));
        }catch (Exception e){
            log.error("优惠券时间格式化失败",e);
        }
        return po;
    }

    public CouponVO detail(Integer id) {
        CouponPO po = couponRepository.getById(id);
        CouponVO vo=null;
        if (po!=null){
            vo=new CouponVO();
            BeanUtils.copyProperties(po,vo);
        }
        return vo;
    }
}
